#ifndef TCP_SERVER_H_
#define TCP_SERVER_H_

#include <map>

#include "netlib/net/call_backs.h"
#include "netlib/net/event/event_loop_threadpool.h"
#include "netlib/net/socket/acceptor.h"

namespace netlib::net {

class InetAddress;
class EventLoop;

class TcpServer {
public:
	TcpServer(EventLoop* loop,
	          const InetAddress& listen_addr,
	          bool is_epoll = false,
	          std::string&& name = "Server",
	          int n_event_thread = 0);
	~TcpServer() = default;

	void SetConnectionCallback(ConnectionCallback&& cb) { conn_cb_ = cb; }
	void SetMessageCallback(MessageCallback&& cb) { msg_cb_ = cb; }
	void SetThreadInitCallback(const ThreadInitCallBack& cb) { thread_init_cb_ = cb; }
	void SetThreadNum(int n) {
		assert(n >= 0);
		event_thread_pool_.SetThreadsNum(n);
	}
	auto GetName() const -> const std::string& { return kName; }

	void Start();
	void DefaultConnectionCallback(const TcpConnectionPtr& conn);

private:
	void NewConnection(int connfd, const InetAddress& peer_addr);
	void RemoveConnection(const TcpConnectionPtr& conn);
	void RemoveConnectionInLoop(const TcpConnectionPtr& conn);

	using ConnectionMap = std::map<std::string, TcpConnectionPtr>;

	// bool is_started_{false};
	const std::string kName;
	EventLoop* loop_;
	Acceptor acceptor_;
	ConnectionCallback conn_cb_{
	    [this](const TcpConnectionPtr& conn) { DefaultConnectionCallback(conn); }};
	MessageCallback msg_cb_{DefaultMessageCallback};
	ConnectionMap connections_;
	ThreadInitCallBack thread_init_cb_;
	EventLoopThreadPool event_thread_pool_;
};

} // namespace netlib::net

#endif // TCP_SERVER_H_